#pragma once
#include<Windows.h>
#include<string>

static char base64EncodeChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static char base64DecodeChars[] = {
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1,
	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
};


class CBase64
{

public:
	CBase64()
	{
	
	}
	~CBase64()
	{
	}

	std::string Base64Encode(const unsigned char *in_bits, const int in_len)
	{
		char *in = (char *)in_bits;
		int i = 0;
		int index = 0;
		unsigned char c1;
		unsigned char c2;
		unsigned char c3;

		std::string strEncode = "";

		while (i < in_len)
		{
			c1 = *(in + i);
			i++;
			if (i == in_len)
			{
				strEncode += base64EncodeChars[(c1 & 0XFF) >> 2];
				strEncode += base64EncodeChars[(c1 & 0X03) << 4];
				strEncode += '=';
				strEncode += '=';
				break;
			}

			c2 = *(in + i);
			i++;
			if (i == in_len)
			{
				strEncode += base64EncodeChars[(c1 & 0XFF) >> 2];
				strEncode += base64EncodeChars[((c1 & 0X3) << 4) | ((c2 & 0XF0) >> 4)];
				strEncode += base64EncodeChars[(c2 & 0X0F) << 2];
				strEncode += '=';
				break;
			}

			c3 = *(in + i);
			i++;
			strEncode += base64EncodeChars[(c1 & 0XFF) >> 2];
			strEncode += base64EncodeChars[((c1 & 0X03) << 4) | ((c2 & 0XF0) >> 4)];
			strEncode += base64EncodeChars[((c2 & 0X0F) << 2) | ((c3 & 0XC0) >> 6)];
			strEncode += base64EncodeChars[c3 & 0X3F];
		}

		return strEncode;
	}

	std::string Base64Decode(const char *in, const int in_len)
	{
		int i = 0;
		int index = 0;
		unsigned char c1;
		unsigned char c2;
		unsigned char c3;
		unsigned char c4;
		std::string strDecode = "";

		if (in_len < 4) {
			return "";
		}

		for (int j = 0; j < in_len; j++) {
			if ((in[j] < 0)
				|| ((unsigned char)in[j] >= 128)
				|| base64DecodeChars[in[j] & 0XFF] == -1) {
				return "";
			}
		}

		while (i < in_len)
		{
			c1 = base64DecodeChars[in[i++] & 0XFF];
			c2 = base64DecodeChars[in[i++] & 0XFF];
			strDecode += (c1 << 2) | ((c2 & 0X30) >> 4);
			c3 = in[i++];
			if (c3 == '=')
			{
				break;
			}

			c3 = base64DecodeChars[c3];
			strDecode += ((c2 & 0XF) << 4) | ((c3 & 0X3C) >> 2);

			c4 = in[i++];
			if (c4 == '=')
			{
				break;
			}
			c4 = base64DecodeChars[c4];
			strDecode += ((c3 & 0X03) << 6) | c4;
		}

		return strDecode;
	}
};
